#ifndef DODO_LINK_STUFF_H
#define DODO_LINK_STUFF_H

#include <string>
#include <stdexcept>

#include <quigon/basic/constants.h>
#include <quigon/basic/basic_utils.h>

namespace quigon
{

// require:
// bool T::load(string), to load from a path.
// bool T::save(string), to save to a path.
// T::T(), default constructor.
template<class T>
class Link_Stuff
{
public:
	typedef T value_type;
	Link_Stuff() : link_path("#"), value() {}
	Link_Stuff(const std::string& link_path0)
			: link_path(link_path0), value()
	{
		if (!load(link_path))
			func_err("Link_Stuff(link_path)", link_path);
	}

	bool change_path(const std::string& new_path)
	{
		std::string temp_path(new_path);
		if (! conv_env(temp_path))
		{
			func_err("Link_Stuff::change_path", new_path);
			return false;
		}
		link_path = temp_path;
		return true;
	}

	bool load(const std::string& new_path = "#")
	{
		try
		{
			if (new_path != "#")
				link_path = new_path;

			if (!conv_env(link_path))
			{
				link_path = "#";
				return false;
			}
			if (link_path.length() == 0)
			{
				link_path = "#";
				return false;
			}

			return value.load(link_path);
		}
		catch (...)
		{
			func_err("Link_Stuff::load()", link_path);
			throw;
		}
	}

	bool save(const std::string& new_path = "#") const
	{
		try
		{
			if (new_path != "#")
			{
				std::string temp_path(new_path);
				if (!conv_env(temp_path))
				{
					func_err("conv_env", temp_path);
					return false;
				}

				return value.save(temp_path);
			}
			// link_path won't be $ENV after loading
			else if (link_path != "#")
				return value.save(link_path);
			else
				return false;
		}
		catch (...)
		{
			func_err("Link_Stuff::save", new_path);
			throw;
		}
	}
	T& operator()()
	{
		return value;    // there will be a lot of ()s...
	}
	const T& operator()() const
	{
		return value;
	}
private:
	std::string link_path;
	T value;
};

}

#endif

